package com.sbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sbx.constants.FileConstant;
import com.sbx.entity.dto.FileOB;
import com.sbx.entity.dto.User;
import com.sbx.mapper.FilesMapper;
import com.sbx.service.FilesService;
import com.sbx.service.UserService;
import com.sbx.utils.MinioUtil;
import com.sbx.utils.RequestUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FilesServiceImpl implements FilesService {

    @Resource
    private MinioUtil minioUtil;
    @Resource
    private UserService userService;
    @Resource
    private FilesMapper filesMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadFile(MultipartFile file, String visit, String parentId, String name, String bucket) {
//        User user = RequestUtil.getUserId(userService);
        FileOB fileOB = new FileOB();
        if (!"public".equals(visit) && !"private".equals(visit)) {
            throw new RuntimeException("权限异常！");
        }

        String minioFileId = UUID.randomUUID().toString().replace("-", "");
        fileOB

                .setCreator("chenxiaodun")
                .setCreated(new Date())
                .setType(FileConstant.FilesType.FILE.getType())
                .setOriginName(file.getName()+ file.getContentType())
//                .setOriginName(name)
                .setParentId(parentId)
                .setMinioFileId(minioFileId)
                .setSize(file.getSize())
                .setVisit(visit)
                //.setCreator(user.getUserName())
                .setBucket(bucket);
        try {
            minioUtil.putObject(bucket, minioFileId, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        filesMapper.insert(fileOB);


    }

    @Override
    public void downFile(String id, HttpServletResponse response) {
        FileOB fileOB = filesMapper.selectById(id);

        InputStream file = minioUtil.getObject(fileOB.getBucket(), fileOB.getMinioFileId());
        try {
            response.setContentType("application/x-download");
            // 文件名中文乱码处理
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileOB.getOriginName(), "utf-8"));
            byte[] buff = new byte[1024];
            try (BufferedInputStream bis = new BufferedInputStream(file);
                 OutputStream outputStream = response.getOutputStream()) {
                response.addHeader("content-length", bis.available() + "");
                int read = bis.read(buff);
                while (read != -1) {
                    outputStream.write(buff, 0, buff.length);
                    outputStream.flush();
                    read = bis.read(buff);
                }
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception ex) {
            ex.printStackTrace();

        }


    }

    @Override
    public void createDir(FileOB fileOB) {
        User user = RequestUtil.getUserId(userService);
        if (StringUtils.isEmpty(fileOB.getVisit())) {
            fileOB.setVisit("public");
        } else if (!"public".equals(fileOB.getVisit()) && !"private".equals(fileOB.getVisit())) {
            throw new RuntimeException("权限异常！");
        }
        if (!user.getId().equals(fileOB.getParentId())) {//判断parentId是否为当前用户id
            LambdaQueryWrapper<FileOB> fileOBLambdaQueryWrapper = new LambdaQueryWrapper<>();
            fileOBLambdaQueryWrapper.eq(FileOB::getId, fileOB.getParentId());
            List<FileOB> fileOBS = filesMapper.selectList(fileOBLambdaQueryWrapper);
            Assert.isTrue(!CollectionUtils.isEmpty(fileOBS), "此文件夹已不存在，无法创建子文件夹!");
        }
        fileOB.setCreator(user.getUserName()).setCreated(new Date());
        filesMapper.updateById(fileOB);
    }

    @Override
    public void putFileOrDir(String id, String name, String visit) {
        FileOB fileOB = filesMapper.selectById(id);
        Assert.notNull(fileOB, "文件/文件夹不存在!");
        if (!StringUtils.isEmpty(visit)) {
            if (!"public".equals(visit) && !"private".equals(visit)) {
                throw new RuntimeException("权限取值范围异常！"+ visit);
            }
        }

        fileOB.setOriginName(name);
        fileOB.setVisit(visit);
        filesMapper.updateById(fileOB);
    }

    @Override
    public void delFileOrDir(String id) {
        FileOB fileOB = filesMapper.selectById(id);
        if (fileOB == null) {
            return;
        }
        delFileOrDir(fileOB);
    }

    public void delFileOrDir(FileOB fileOB) {
        if (!FileConstant.FilesType.DIR.getType().equalsIgnoreCase(fileOB.getType())) {
            minioUtil.delObject(fileOB.getBucket(), fileOB.getMinioFileId());
            filesMapper.deleteById(fileOB.getId());
            return;
        }
        filesMapper.deleteById(fileOB.getId());
        LambdaQueryWrapper<FileOB> fileOBLambdaQueryWrapper = new LambdaQueryWrapper<>();
        fileOBLambdaQueryWrapper.eq(FileOB::getParentId, fileOB.getId());
        List<FileOB> fileOBS = filesMapper.selectList(fileOBLambdaQueryWrapper);
        if (CollectionUtils.isEmpty(fileOBS)) {
            return;
        }
        for (FileOB ob : fileOBS) {
            delFileOrDir(ob);
        }
    }

    @Override
    public void cpFile() {

    }

    @Override
    public Page<FileOB> fileList(String id, Boolean self, Integer pageIndex, Integer pageSize) {
        Page<FileOB> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<FileOB> wrapper = new LambdaQueryWrapper<FileOB>();

        wrapper.eq(Boolean.FALSE.equals(self), FileOB::getId, id)
                .eq(Boolean.TRUE.equals(self), FileOB::getParentId, id);


        page = filesMapper.selectPage(page, wrapper);
        List<FileOB> fileOBs = page.getRecords();
        for (FileOB fileOB : fileOBs) {
            fileList(fileOB);
        }


        page.setRecords(fileOBs);


        return page;
    }

    private void fileList(FileOB fileOB) {
        if (fileOB == null || !FileConstant.FilesType.DIR.getType().equalsIgnoreCase(fileOB.getType())) {
            return;
        }
        LambdaQueryWrapper<FileOB> fileOBLambdaQueryWrapper = new LambdaQueryWrapper<>();
        fileOBLambdaQueryWrapper.eq(FileOB::getParentId, fileOB.getId());
        List<FileOB> fileOBS = filesMapper.selectList(fileOBLambdaQueryWrapper);
        fileOB.setChildren(fileOBS);
        if (!CollectionUtils.isEmpty(fileOBS)) {
            for (FileOB ob : fileOBS) {
                fileList(ob);
            }
        }
    }
}
